package realm.md5realm;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

/**
 * 散列凭证由盐和密码组成，采用md5加密的验证器realm
 * 
 * @author fidel
 *
 */
public class CustomMd5Realm extends AuthorizingRealm {
    /**
     * <b>获取授权信息</b>时的操作
     * <p>
     * 从底层数据存储中为给定的委托人检索AuthorizationInfo
     * <p>
     * 当从这个方法返回一个实例时，你可能要考虑使用SimpleAuthorizationInfo的实例，因为它在大多数情况下是合适的
     * <p>
     * 此方法在当前类中没有实现意义
     * 
     * @see realm.CustomRealm#doGetAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection)
     * @param principals 应被检索的授权信息的主要识别原则
     * @return 与该委托人相关的授权信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        Class<? extends CustomMd5Realm> clazz = this.getClass();
        try {
            throw new RuntimeException(clazz.getName() + "的"
                + clazz.getDeclaredMethod("doGetAuthorizationInfo", PrincipalCollection.class) + "的实现没有意义");
        } catch (NoSuchMethodException | SecurityException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("调用doGetAuthenticationInfo方法");
        // 获取认证过程中提交的账户身份
        String principal = (String) token.getPrincipal();
        System.out.println("token用户名：" + principal);
        // 获取token的凭证并强制将其转换为字符数组
        char[] credentials = (char[]) token.getCredentials();
        System.out.println("token密码：" + String.valueOf(credentials));
        /*以账户身份为参数，从数据库中查询单行记录
        对查询得到的单行记录进行校验，如果部分字段的值不符合要求则返回null*/
        if (!principal.equals("omega")) {
            return null;
        }
        /*模拟从数据库中查询得到的散列凭证
        由凭证盐与明文密码组合而成的值经过散列后即散列凭证，此处的明文密码是last*/
        String hashedCredentials = "274bcfd9f4c349f7fee759785e9b148b";
        // 模拟从数据库中查询得到的盐
        String salt = "md5-salt@";
        // 返回简单验证信息
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, hashedCredentials,
            ByteSource.Util.bytes(salt), this.getName());
        System.out.println("验证信息凭证：" + info.getCredentials());
        System.out.println("验证信息凭证盐：" + new String(info.getCredentialsSalt().getBytes()));
        return info;
    }
}
